#pragma once
#include "threadsync.h"
#include "SimpleMemPool.h"
#include "Thread.h"
#include <deque>
using namespace std;
const int FRAME_QUEUE_DEFAULT_CAPACITY = 16*1024*1024;
enum QUEUE_ACTION
{
	ACTION_GET_NEXT_FRAME,//continue Get the next frame
	ACTION_STOP_GET_FRAME,//stop getting the next frame
	ACTION_GET_TIME_OUT, //get the current frame timeout
	ACTION_GET_FAILED,  //get the current frame fail
	ACTION_GET_DISABLED
};

typedef QUEUE_ACTION (*GET_FRAME_PROC)(unsigned char* pData, int nSize,__int64 timeStamp, void* pUserData);
typedef void (*END_GET_PROC)(void *pUserData);

class RawYUVFrameQueue
{
	struct FRAME_DATA
	{
		int nDispHeight;
		int nDispWidth;
		int nCapacity;
		int nDataSize;
		__int64 timeStamp;
		BOOL bKeyFrame;
		unsigned int nFrameCount;	
		BYTE pData[1];
	};

	typedef deque<FRAME_DATA*> CFrameDataQueue;
public:
	RawYUVFrameQueue(void);
	~RawYUVFrameQueue(void);

	void Initialize(int nCapacity = FRAME_QUEUE_DEFAULT_CAPACITY);
	BOOL PushRawFrameData(const unsigned char* pData, int nSize,int DispHeight,int DisWidth,BOOL bKeyFrame, __int64 timeStamp);
    QUEUE_ACTION GetOneFrameData(GET_FRAME_PROC pGetFrameProc,DWORD dwWaitTime , void* pUserData);
	BOOL StartGetFrameThread(GET_FRAME_PROC pGetFrameProc,void* pUserData);
	void StopGetFrameThread();
    void Close(END_GET_PROC pEndGetProc,void* pUserData);
private:
	static DWORD GetFrameThreadProc(LPVOID pParam);
	void GetFrameProc();
	FRAME_DATA* AllocFrameDataBuffer(int nBufferSize);
	void FreeFrameDataBuffer(FRAME_DATA* pFrameData);

	void PushFrameData(FRAME_DATA* pFrameData);//EnQUE
	void  PopFrameData();

	int m_nCapacity;     
	int m_nDataBytesInQueue;
	CFrameDataQueue  m_DataQueue;
	FRAME_DATA* m_pFrameBuffer;

	HANDLE m_bDataEvent;
	HANDLE m_bStopDequeueEvent;

	CSimpleMemPool<FRAME_DATA> m_FrameBuffer;

	CCriticalSection m_DataQueueCS;
	BOOL m_bClosed;
	BOOL m_bGetFrame;
	BOOL m_bGetThreadStopped;
	CThread m_GetFrameThread;

	GET_FRAME_PROC  m_pGetFrameProc;
	void* m_pUserData;

};
